perm filename TCPOPT.MAC[IP,SYS] blob
sn#680224 filedate 1982-10-14 generic text, type T, neo UTF8
;CWL:<403-TCP>TCPOPT.MAC.40303 2-May-82 16:56:04, Edit by CLYNN
; Fix TLH not 32 bit bug
; Added new option routines. Old ones in limbo
;<403-TCP>TCPOPT.MAC.40301 29-Jan-82 15:05:57, Edit by CLYNN
; Updated for TCP release 3
SEARCH INPAR,TCPPAR,PROLOG
TTITLE TCPOPT
SUBTTL TCP Option Routines, William W. Plummer, 5FEB77
SWAPCD
COMMENT !
These routines perform various functions associated with
TCP and Internet Options. Options are stored in packets
after the header and before the data. The format is
described in TCPPAR.
* TCPIIO ... 3 ...... Insert (or refresh) IP options
* TCPITO ... 5 ...... Insert TCP options
OPSAV .... 6 ...... Save registers for option routines
6 ...... Internal register definitions
7 ...... Option tables
* TCPUOP ... 9 ...... Process & merge User options
PARSOP ... 10 ...... Parse and validate user specified options
LSRCHK ... 11 ...... Validate Loose Source Route option
SSRCHK ... 11 ...... Validate Strict Source Route option
* TCPXIO ... 12 ...... Extract, process & merge IP options
* TCPXTO ... 12 ...... Extract, process & merge TCP options
TCPXXO ... 13 ...... Work routine for TCPXIO & TCPXTO
MSLXCT ... 15 ...... Process TCP Max Seg Len option
MERGE .... 16 ...... Merge User & Received options
MERGED ... 17 ...... Drop option from merge
RRTCPY ... 18 ...... Invert received RRT option to SSR
LSRCPY ... 19 ...... Invert received LSR option
SSRCPY ... 19 ...... Invert received SSR option
TSPCPY ... 21 ...... Copy received TSP option
SIDCPY ... 21 ...... Copy received SID option
22 ...... IP/TCP Information tables
OPRES .... 22 ...... Restore saved registers
* SNDSOP ... 23 ...... Send Secure Open (Internet)
* SNDSCL ... 23 ...... Send Secure Close (Internet)
* SETLAB ... 24 ...... Set debugging label (TCP)
* GETLAB ... 24 ...... Get debugging label (TCP)
* RSVTSO ... 25 ...... Reserve space for a local timestamp option (TCP)
* SETTSO ... 25 ...... Set the value field of local timestamp (TCP)
* GETTSO ... 25 ...... Get the value field from local timestamp (TCP)
* SETRBS ... 26 ...... Set receive buffer size option (TCP)
* GETRBS ... 26 ...... Get receive buffer size (TCP)
GET4 ..... 27 ...... Get a 4-byte value
SET4 ..... 27 ...... Set a 4-byte value
INOPTR ... 28 ...... Get byte pointer for adding an Internet option
TCOPTR ... 29 ...... Get byte pointer for adding a TCP option
FNINOP ... 30 ...... Get byte pointer for reading an Internet opton
FNTCOP ... 30 ...... Get byte pointer for reading a TCP opton
SCANOP ... 31 ...... Lookup an option
!
; TCPIIO Insert IP Options (from TCB image) into packet
; PKT/ (ext) pointer to packet being constructed
; TCB/ (ext) pointer to TCB or 0
; CALL TCPIIO
;Ret+1: Always, Any options inserted & PIPL & PIDO updated accordingly
TCPIIO::JUMPE TCB,TCPIIX ; No TCB
LOAD T1,TIPDO,(TCB) ; TOTAL IP header size, words
SUBI T1,<MINIHS+3>/4 ; Minus standard header
JUMPLE T1,TCPIIX ; No IP options
LOAD T2,PIDO,(PKT) ; IP header size, words
CAIE T2,<MINIHS+3>/4 ; Insert or refresh?
JRST TCPII5 ; Refresh
; Insert options
ADD T1,T2 ; Desired header+options
CAILE T1,.RTJST(-1,PIDO) ; Too big?
MOVX T1,.RTJST(-1,PIDO) ; Clamp to max
STOR T1,PIDO,(PKT) ; Update IP header size, words
SUB T1,T2 ; Room for options, words
MOVE T4,T1 ; Option words
LSH T4,2 ; Bytes in option words
LOAD T2,PIPL,(PKT) ; Current packet length
ADD T2,T4 ; New packet length, bytes
STOR T2,PIPL,(PKT) ; Updated packet length
JRST TCPII8
; Refresh options
TCPII5: MOVE T1,T2 ; Available space
SUBI T1,<MINIHS+3>/4 ; for options
TCPII8:
; Copy options into header
XMOVEI T2,TCBIO(TCB) ; Option image in TCB
XMOVEI T3,PKTELI(PKT) ; IP header base
ADDI T3,<MINIHS+3>/4 ; Pointer to IP option area
CALL XBLTA ; Options into header
TCPIIX:
RET
REPEAT 0,<
SKIPN TCB ; Have a TCB?
RET ; No, no options
; If the TCP is running in secure mode, include a Secure Open
; (i.e., connection change request) if the security level has changed.
; Do this for a SYN packet too even though the level will most likely
; be 0. This means "security level not yet known" to the KDC.
LOAD T1,TSSYN,(TCB) ; Get send state
LOAD T2,TSLVN,(TCB) ; "Next" Security Level
LOAD T3,TSLVC,(TCB) ; "Current" level
CAIE T1,SYNABL ; About to send a SYN?
CAME T2,T3 ; Or difference in levels?
SKIPN INTSCR ; And running in secure mode?
CAIA ; No.
CALL SNDSOP ; Yes. Send the option
RET
> ; End of REPEAT 0
; TCPITO Insert TCP options (from TCB image) into packet
; PKT/ (ext) pointer to packet being constructed
; TPKT/ (ext) pointer to TCP portion of packet
; TCB/ (ext) pointer to TCB or 0
; CALL TCPITO
;Ret+1: Always, any options copied & PIPL and PTDO updated
TCPITO::JUMPE TCB,TCPITX ; No TCB
LOAD T1,TTPDO,(TCB) ; TOTAL TCP header size, words
SUBI T1,<MINTHS+3>/4 ; Minus standard header
JUMPLE T1,TCPITX ; No TCP options
LOAD T2,PTDO,(TPKT) ; TCP header size, words
MOVE T3,TPKT ; TCP header base
ADD T3,T2 ; Pointer to TCP option area
ADD T1,T2 ; Desired header+options
CAILE T1,.RTJST(-1,PTDO) ; Too big?
MOVX T1,.RTJST(-1,PTDO) ; Clamp to max
STOR T1,PTDO,(TPKT) ; Update TCP header size, words
SUB T1,T2 ; Room for options, words
MOVE T4,T1 ; Option words
LSH T4,2 ; Bytes in option words
LOAD T2,PIPL,(PKT) ; Current packet length
ADD T2,T4 ; New packet length, bytes
STOR T2,PIPL,(PKT) ; Updated packet length
XMOVEI T2,TCBTO(TCB) ; Option image in TCB
CALL XBLTA ; Options into header
TCPITX:
RET
REPEAT 0,<
AOSA T1,NXTLBL ; Get next packet label
JFCL
SKIPE INTTRC ; Tracing packets?
CALL SETLAB ; Store in packet (LBLOPT)
SKIPE STATF ; Taking statistics right now?
CALL RSVTSO ; Yes, reserve timestamp option space
SKIPN TCB ; Have a TCB?
RET ; No, no more options
RET
> ; End of REPEAT 0
; Maximum # words for options
MAXIOW==1←<WID(PIDO)>-1-<MINIHS+3>/4 ; Max # IP option words
MAXTOW==1←<WID(PTDO)>-1-<MINTHS+3>/4 ; Max # TCP option words
MAXOPW==MAXIOW ; Max of the two
IFG <MAXTOW-MAXIOW>,<MAXOPW==MAXTOW>
; AC redefinitions - Temp and Local register definitions initiated
; by CALL OPSAV
OPSAV: STACKL <UPTRS,<UOPS,MAXOPW+1>,<REGS,11+1>>
MOVEM 11,11+REGS ; Save last reg
MOVEI 11,REGS ; 0,,save area adr
BLT 11,11-1+REGS ; Save others
MOVX CX,<MSEC1,,R> ; Wipe out our
EXCH CX,-2+UPTRS ; return with dummy
CALL (CX) ; Back to mainline
JRST OPRES ; Go clean up stack
OPTS==0 ;DEFAC(OPTS,FR) ; Bit corresponding to options present
RP==2 ;DEFAC(RP,T2) ; Pointer to received option byte
RC==3 ;DEFAC(RC,T3) ; Count of remaining received option bytes
BIT==4 ;DEFAC(BIT,T4) ; Bit corresponding to current option
OPT==5 ;DEFAC(OPT,Q1) ; Option (byte)
OPL==6 ;DEFAC(OPL,Q2) ; Option length
OPC==7 ;DEFAC(OPC,Q3) ; Count of remaining option bytes
OPP==10 ;DEFAC(OPP,P1) ; Pointer to option byte
IORT==11 ;DEFAC(IORT,11) ; Pointer to IP or TCP Info table
; TPKT
; PKT
; TCB
; Option Tables
DEFINE OPTION (T,NA,C,NU,L,U,R,E)<
EXP NU
> ; End of DEFINE OPTION
-NIPOP,,.+1 ; IP option numbers
IOPNU: IPOPTS
NIPOP==.-IOPNU ; # IP options
ENDOPT
-NTCPOP,,.+1 ; TCP option numbers
TOPNU: TCPOPTS
NTCPOP==.-TOPNU ; # TCP options
ENDOPT
DEFINE OPTION (T,NA,C,NU,L,U,X)<
IFDEF NA'U,< MSEC1,,NA'U >
IFNDEF NA'U,< MSEC1,,X >
> ; End of DEFINE OPTION
OPTCOF==.-IOPNU ; Is user option valid
IPOPTS (CHK,RSKP) ; Known IP Options
MSEC1,,RSKP ; Unknown IP Options - OK if cannot prove wrong
MSEC1,,RSKP ; Maintain spacing
TCPOPTS (CHK,RSKP) ; Known TCP Options
MSEC1,,RSKP ; Unknown TCP Options - OK if cannot prove wrong
OPTDOF==.-IOPNU ; Should received option be dropped or sent?
IPOPTS (CPY,R) ; Known IP Options
MSEC1,,R ; Unknown IP Options - Drop unknowns
MSEC1,,R ; Maintain spacing
TCPOPTS (CPY,R) ; Known TCP Options
MSEC1,,R ; Unknown TCP Options - Drop unknowns
OPTXOF==.-IOPNU ; What does received option mean?
IPOPTS (XCT,R) ; Known IP Options
MSEC1,,R ; Unknown IP Options - Forget unknowns
MSEC1,,R ; Maintain spacing
TCPOPTS (XCT,R) ; Known TCP Options
MSEC1,,R ; Unknown TCP Options - Forget unknowns
DEFINE OPTION (T,NA,C,NU,L,U,R,E)<
NA'LEN==L
> ; End of DEFINE OPTION
IPOPTS
TCPOPTS
; Process User specified options
; T1/ (ip,,tcp) user section 0 option addresses (or -1 to re-merge)
; TCB/ (ext) pointer to locked connection block
; CALL TCPUOP
;Ret+1: Always, T1 is 0 or error code
TCPUOP::CALL OPSAV ; Save regs & get working area
MOVEM T1,UPTRS ; Save user addresses
HLRZ T2,UPTRS ; User address of IP options
JUMPE T2,TCPUO2 ; None
XMOVEI IORT,IPINFO ; IP Info
SETZ T1, ; Incase re-merge
CAIE T2,-1 ; Skip PARSOP if re-merge
CALL PARSOP ; Parse and validate user specified options
JUMPN T1,TCPUOX ; Error
CALL MERGE ; Merge new user options with received
TCPUO2:
HRRZ T2,UPTRS ; User address of TCP options
JUMPE T2,TCPUO4 ; None
XMOVEI IORT,TCPINFO ; TCP Info
SETZ T1, ; Incase re-merge
CAIE T2,-1 ; Skip PARSOP if re-merge
CALL PARSOP ; Parse and validate user specified options
JUMPN T1,TCPUOX ; Error
CALL MERGE ; Merge new user options with received
TCPUO4:
SETZ T1, ; All ok
TCPUOX: MOVEM T1,T1+REGS ; Return value
RET
; PARSOP Parse and validate user specified options
; T2/ (section 0) user address of options (non-zero if here)
; IORT/ (Ext) pointer to IP or TCP Info table
; CALL PARSOP
;Ret+1: Always, T1 non-zero if error
PARSOP: SETZM OPTS ; No user options yet
MOVE T1,MXW(IORT) ;MAXxOW ; Max possible length, w
XMOVEI T3,UOPS ; Our local copy
CALL BLTUM ; Get user options
MOVE T3,MXW(IORT) ;MAXxOW ; Maximum length, w
LSH T3,2 ; Bytes
MOVE OPC,T3 ; Used later too
MOVX OPP,<POINT 8,UOPS,7> ; Byte pointer to first
PARSO2: LDB OPT,OPP ; Get option
ANDCM OPT,CPY(IORT) ;CPYOPT/0 ; Without copy on fragmentation
CAIN OPT,ENDOPT ; End?
JRST PARSO6 ; Yes
CAIN OPT,NOPOPT ; NOP?
JRST PARSO4 ; Yes
MOVE T1,OTAB(IORT) ;MSEC1,,xOPNU ; Address of option table
MOVE T1,-1(T1) ; -count,,address of first
CAME OPT,(T1) ; This it?
AOBJN T1,.-1 ; No, try next
HLRE BIT,T1 ; -i or 0
SKIPE BIT ; Unknown option
MOVE BIT,BITS+↑D36(BIT) ; Known option
CALL @OPTCOF(T1) ; Check option
JRST PARSO9 ; Looses
ILDB OPT,OPP ; Get length (maybe)
CAIL OPC,2 ; Enough for length?
CAMGE OPC,OPT ; Enough for option?
JRST PARSO9 ; No, error
IORM BIT,OPTS ; Remember option exists
SUBI OPC,1 ; Count option byte
SUBI OPT,1 ; Already past it
IFN NOPOPT-1,<
CAIA
PARSO4: MOVX OPT,1 ; Option length is 1 (NOPOPT)
> ; End of IFN NOPOPT-1
IFE NOPOPT-1,<PARSO4:> ; OPT code is length
SUB OPC,OPT ; Free bytes after this option
ADJBP OPT,OPP ; Point at next
MOVEM OPT,OPP
JUMPG OPC,PARSO2 ; Back for next option
PARSO6:
SUB T3,OPC ; Used bytes
JUMPLE OPC,PARSO7 ; No free bytes
SETZ T1,
IDPB T1,OPP ; Clear free bytes
SOSLE OPC
JRST .-2
PARSO7:
XCT SOU(IORT) ;STOR T3,TxPOU,(TCB) ; Store user option bytes
MOVE T1,MXW(IORT) ;MAXxOW ; Max possible length, w
XMOVEI T2,UOPS ; New options
XCT XTOU(IORT) ;XMOVEI T3,TCBxU(TCB) ; TCB location
CALL XBLTA ; Copy them there
XCT SOF(IORT) ;STOR OPTS,TxOPF,(TCB) ; Save flags
TDZA T1,T1 ; No error
PARSO9: HRROI T1,ELP+↑D2 ; Error
RET
; Make sure routing options end with packet source address
; T1/ Option table index (free)
; T2/ (free)
; T3/ Max count (preserve)
; T4=BIT/ Bit representing option (preserve)
; OPT/ Option code w/o CPYOPT (free)
; OPP/ Pointing at option code byte (preserve)
; OPC/ Remaining count (preserve)
; TCB/ Locked (ext) TCB address
; CALL LSRCHK or SSRCHK
; Return+1 Error in option
; Return+2 Ok
LSRCHK: SSRCHK:
PUSH P,OPP ; Save pointer
JE TLH,(TCB),RUTCKO ; Not yet specified so cannot check
ILDB T2,OPP ; Length
ILDB OPT,OPP ; Initial pointer
CAIL T2,7 ; 7 is leagal but 13(8) is reasonable
CAIE OPT,4
JRST RUTCKE ; Bad
SUBI T2,3 ; Option header length
RUTCKL: ILDB OPT,OPP ; Next address byte
LSH T1,↑D8 ; Room for another byte
IOR T1,OPT ; of address
SOSLE T2 ; More bytes?
JRST RUTCKL ; Yes
ANDX T1,<BYTE (4)0(8)377,377,377,377> ; Just last 4 bytes
LOAD T2,TLH,(TCB) ; Source
CAMN T1,T2 ; Same?
RUTCKO: AOS -1(P) ; OK, skip return
RUTCKE: POP P,OPP ; Restore register
RET
; Extract interesting IP options from received packet
; PKT/ (ext) pointer to IP header
; TCB/ (ext) pointer to locked TCB
; CALL TCPXIO
;Ret+1: Always, options updated/processed
TCPXIO::LOAD T1,PIDO,(PKT) ; IP header size, w
SUBI T1,<MINIHS+3>/4 ; Size w/o options
JUMPLE T1,TCPXIX ; None
CALL OPSAV ; Save regs & get working area
MOVE T2,PKT
ADDI T2,PKTELI+<MINIHS+3>/4
XMOVEI IORT,IPINFO ; IP Info
CALL TCPXXO ; Process received IP options
TCPXIX:
RET
; Extract interesting TCP options from received packet
; TPKT/ (ext) pointer to TCP header
; TCB/ (ext) pointer to locked TCB
; CALL TCPXTO
;Ret+1: Always, options updated/processed
TCPXTO::LOAD T1,PTDO,(TPKT) ; TCP header size, w
SUBI T1,<MINTHS+3>/4 ; Size w/o options
JUMPLE T1,TCPXTX ; None
CALL OPSAV ; Save regs & get working area
MOVE T2,TPKT
ADDI T2,<MINTHS+3>/4
XMOVEI IORT,TCPINFO ; TCP Info
CALL TCPXXO ; Process TCP options
TCPXTX:
RET
; Scan options
; T1/ # option words
; T2/ (ext) pointer to options in packet
; IORT/ (Ext) Information table address
; CALL TCPXXO
;Ret+1: Always
TCPXXO: PUSH P,T1 ; Save received option words
SETZM UOPS ; Clear working area
MOVEI T4,UOPS ; Build BLT word
HRLS T4
ADDI T4,1 ; But save T2
BLT T4,MAXOPW-1+UOPS
MOVE T1,(P) ; Words received
XMOVEI T3,UOPS
CALL XBLTA ; Get options from packet
MOVE RC,(P) ; Words received
LSH RC,2 ; Bytes
MOVEM RC,(P) ; Save for later
MOVX RP,<POINT 8,UOPS,7> ; First received option
TCPXX3: LDB OPT,RP ; Reveived option byte
ANDCM OPT,CPY(IORT) ;CPYOPT/0 ; Without copy on fragmentation
CAIN OPT,ENDOPT ; End of options?
JRST TCPXX7 ; Yes, all done
CAIN OPT,NOPOPT ; Watch out for length 1
JRST TCPXX5
MOVE T1,OTAB(IORT) ;MSEC1,,xOPNU ; Option table address
MOVE T1,-1(T1) ; AOBJN pointer for options
CAME OPT,(T1) ; This the option?
AOBJN T1,.-1 ; No, look further
ILDB OPT,RP ; Get option length
CALL @OPTXOF(T1) ; Interpret option
LDB OPT,RP ; Option length
SUBI RC,1 ; Count option code
SUBI OPT,1 ; Already past it
IFN NOPOPT-1,<
CAIA
TCPXX5: MOVX OPT,1 ; Option length is 1 (NOPOPT)
> ; End of IFN NOPOPT-1
IFE NOPOPT-1,<TCPXX5:> ; OPT code is length
SUB RC,OPT ; Bytes left to process
ADJBP OPT,RP ; Option byte
MOVEM OPT,RP
JUMPG RC,TCPXX3 ; Loop if more
TCPXX7:
MOVNS RC
ADD RC,(P) ; Acutal option bytes
XCT SOR(IORT) ;STOR RC,TxPOR,(TCB)
SUB P,BHC+1 ; Restore stack
MOVE T1,MXW(IORT) ;MAXxOW
XMOVEI T2,UOPS
XCT XTOR(IORT) ;XMOVEI T3,TCBxR(TCB)
CALL XBLTA ; Save options for future
CALL MERGE ; Merge them with user's
RET
; Received TCP Maximum Segment Length Option
; RP/ Points to length byte
; CALL MSLXCT
;Ret+1: Always, TSMXP updated if possible
MSLXCT: PUSH P,RP ; Save temps
PUSH P,RC
MOVE T3,RP
LDB T4,T3 ; Get length
CAIE T4,MSLLEN ; Right length?
JRST MSLXCX ; No, ignore
; (ICMP error msg??)
SETZ T1,
MOVX T4,<-2,,0> ; Two more bytes
MSLXC4: ILDB T2,T3 ; Accumulate #
LSH T2,↑D<36-8>
LSHC T1,↑D8
AOBJN T4,MSLXC4
CALL TCPMXP ; Compute new segment length
MSLXCX: POP P,RC
POP P,RP
RET
; MERGE User options and received options into send options
; IORT/ IP/TCP Information table address
; CALL MERGE
MERGE: XCT XFOU(IORT) ;XMOVEI T2,TCBxU(TCB) ; Assume User options
XCT LOU(IORT) ;LOAD OPP,TxPOU,(TCB) ; User bytes used
XCT LOR(IORT) ;LOAD RC,TxPOR,(TCB) ; Received bytes used
JUMPE RC,MERGE8 ; Nothing to merge - User only
MOVE OPC,MXW(IORT) ;MAXxOW ; Max words allowed
LSH OPC,2 ; Max bytes allowed
SUB OPC,OPP ; Free bytes after User
JUMPLE OPC,MERGE8 ; No room for merge - User only
; Either merge or copy/drop received options
ADJBP OPP,[POINT 8,UOPS,7] ; Point at free output byte
MOVE T1,MXW(IORT) ;MAXxOW ; Begin with User options
XMOVEI T3,UOPS ; Get user options
CALL XBLTA
MOVE RP,POR(IORT) ;POINT 8,TCBxR(TCB),7>) ; Received options
XCT LOR(IORT) ;LOAD RC,TxPOR,(TCB) ; Get received bytes
XCT LOF(IORT) ;LOAD OPTS,TxOPF,(TCB) ; Get User option flags
MERGE3: LDB OPT,RP ; Reveived option byte
ANDCM OPT,CPY(IORT) ;CPYOPT/0 ; Without copy on fragmentation
CAIN OPT,ENDOPT ; End of options?
JRST MERGE5 ; Yes, All done
CAIN OPT,NOPOPT ; Nop?
JRST [SUBI RC,1 ; Length
ILDB OPT,RP ; Point at next
JRST MERGE4] ; Go to loop
; Option with length
MOVE T1,OTAB(IORT) ;MSEC1,,xOPNU ; Option table address
MOVE T1,-1(T1) ; AOBJN pointer for options
CAME OPT,(T1) ; This the option?
AOBJN T1,.-1 ; No, look further
HLRE BIT,T1 ; -i (or 0)
SKIPE BIT
MOVE BIT,BITS+↑D36(BIT) ; 1B<36-i>
LDB OPT,RP ; Copy option
DPB OPT,OPP
ILDB OPT,RP ; Get length
SUB RC,OPT ; Received bytes after this option
MOVEI OPL,-1(OPT) ; # bytes left to copy in this option
TRNN OPTS,(BIT) ; If User specified, drop
CAMLE OPT,OPC ; or if not enough space
CAIA ; Go drop it
CALL @OPTDOF(T1) ; Try to copy it
CALL MERGED ; Drop it
MERGE4:
SKIPLE RC ; If more left
JUMPG OPC,MERGE3 ; and room, loop
MERGE5:
MOVX OPT,ENDOPT ; End options (may overflow
DPB OPT,OPP ; into guard word ending UOPS)
XMOVEI T2,UOPS ; Copy from merged
MOVE OPP,MXW(IORT) ;MAXxOW ; Maximum option words
LSH OPP,2 ; Bytes
SUB OPP,OPC ; Used bytes
MERGE8: ;(T2,OPP) Enter here if no merge, just copy user to send
ADDI OPP,3 ; Round bytes up to
LSH OPP,-2 ; Option words used
SKIPE OPP ; If none, 0 is ok
ADDI OPP,<MINIHS+3>/4 ; Including header
XCT SDO(IORT) ;STOR OPP,TxPDO,(TCB) ; Set send header length
MOVE T1,MXW(IORT) ;MAXxOW ; Maximum option words
XCT XTOO(IORT) ;XMOVEI T3,TCBxO(TCB) ; To TCB image
CALL XBLTA ; Go the options
RET
; MERGED Drop option from net
; RP/ Points at Len byte
; OPT/ Len of option
; OPL/ Len-1 of option
; OPC/ Len of option
; OPP/ Points at output option byte (already copied)
; CALL MERGED
; RP/ Points at next option
; OPC/ Unchanged since none used
; OPP/ Unchanged since none used
MERGED: ADJBP OPL,RP
MOVEM OPL,RP ; Point at next
RET
; Change Record Route from net into Strict Source Route for reply
; RP/ Points at Len byte
; OPT/ Len of option
; OPL/ Len-1 of option
; OPC/ Len of option
; OPP/ Points at output option byte (already copied)
; CALL RRTCPY
;Ret+1: Option should be dropped
;Ret+2: Option was copied and
; RP/ Points at next option
; OPC/ Count reduced if copied
; OPP/ Pointer updated if copied
RRTCPY: PUSH P,[0] ; Turn it into a (trimmed) SSR
MOVE T1,RP ; Peek ahead at
ILDB T4,T1 ; Pointer
CAIN OPT,-1(T4) ; At end? (Len vs (Ptr)-1)
JRST RRTDS2 ; Yes
MOVE T1,OPT ; Len reserved for RRT
MOVEI OPT,-1(T4) ; Len actually used
SUB T1,OPT ; Unused bytes in RRT option
MOVEM T1,(P) ; Save for RP adjustment
RRTDS2:
MOVX T1,SSROPT ; Change RRT
DPB T1,OPP ; to SRT
CALL NUSSR ; Process as Strict Source Route
JRST RRTDSX ; Have to drop it (OPL still Len-1)
POP P,T1 ; Unused bytes in RRT are
ADJBP T1,RP ; Skipped
MOVEM T1,RP ; over
AOS (P) ; All OK return
RET
RRTDSX: SUB P,BHC+1 ; Clear stack of unused RRT bytes
RET ; Dropped return
; Invert Record Route or Loose or Strict Source Route from net for reply
; RP/ Points at Len byte
; OPT/ Len of option
; OPL/ Len-1 of option
; OPC/ Len of option
; OPP/ Points at output option byte (already copied)
; CALL LSRCPY or SSRCPY or NUSSR
;Ret+1: Option should be dropped
;Ret+2: Option was copied and
; RP/ Points at next option
; OPC/ Count reduced if copied
; OPP/ Pointer updated if copied
LSRCPY:
SSRCPY: ; Invert address list
MOVE T1,RP ; Peek ahead at
ILDB T4,T1 ; LSR/SSR pointer
TRNN T4,3 ; Pointer multiple of 4 and
CAIE OPT,-1(T4) ; At end? (Len vs (Ptr)-1)
RET ; No, error, drop it (shouldn't get here)
NUSSR: PUSH P,RC ; Save register for our use
PUSH P,OPP ; Pointer to (copied) option code
IDPB OPT,OPP ; Copy option length
SUB OPC,OPT ; Remaining free bytes tobe
ILDB RC,RP ; Old pointer changed to
LSH RC,-2 ; Counter of addresses
SUBI RC,1 ; (omit code,len,ptr)
MOVX OPT,4 ; Initial pointer
IDPB OPT,OPP
PUSH P,[-1] ; Marker
INVRI: MOVX T4,<-4,,0> ; Collect 4-byte addresses
PUSH P,BHC ;[0] ; here
MOVX T1,<POINT 8,(P),3> ; Point to it (right justified)
ILDB OPT,RP
IDPB OPT,T1 ; Pack
AOBJN T4,.-2
SOSLE RC
JRST INVRI ; Another address to pack
INVRO: MOVX T4,<-4,,0> ; Pack 4-byte addresses
MOVX T1,<POINT 8,(P),3> ; From top of stack (right justified)
ILDB OPT,T1
IDPB OPT,OPP ; Into send option
AOBJN T4,.-2
POP P,T1 ; Save processed address
SKIPL (P) ; Reached marker?
JRST INVRO ; No, do another
SUB P,BHC+1 ; Drop marker
LOAD T4,TFH,(TCB) ; Destination must be last address in route
CAIN T1,T4 ; Same as last?
JRST NDSSR ; Yes all ok
MOVE T1,(P) ; Pointer to option code byte
MOVX OPT,LSROPT ; If adding, make into loose route
DPB OPT,T1
ILDB OPT,T1 ; Must increase length by another address
ADDI OPT,4
DPB OPT,T1
SUBI OPC,4 ; Using 4 more bytes
JUMPL OPC,NDSSR ; Overran max header length, lose
MOVEM T4,(P) ; Have to append destination address
MOVX T4,<-4,,0> ; Pack 4-byte addresses
MOVX T1,<POINT 8,(P),3> ; From top of stack (right justified)
ILDB OPT,T1
IDPB OPT,OPP ; Into send option
AOBJN T4,.-2
NDSSR: SUB P,BHC+1 ; Drop pointer to option byte
ILDB OPT,RP ; Point at next received and
ILDB OPT,OPP ; Send option position
POP P,RC ; Restore register
AOS (P) ; Skip return since copied
RET
; Copy Received option if reserved space not all used
; RP/ Points at Len byte
; OPT/ Len of option
; OPL/ Len-1 of option
; OPC/ Len of option
; OPP/ Points at output option byte (already copied)
; CALL TSPCPY
;Ret+1: Option should be dropped
;Ret+2: Option was copied and
; RP/ Points at next option
; OPC/ Count reduced if copied
; OPP/ Pointer updated if copied
TSPCPY:
MOVE T1,RP ; Peek ahead at
ILDB T4,T1 ; Pointer
CAIN OPT,-1(T4) ; At end? (Len vs (Ptr)-1)
RET ; Yes, drop it
; No, fall into copy
; Fall into copy
; Copy Received option
; RP/ Points at Len byte
; OPT/ Len of option
; OPL/ Len-1 of option
; OPC/ Len of option
; OPP/ Points at output option byte (already copied)
; CALL SIDCPY
;Ret+1: Option should be dropped
;Ret+2: Option was copied and
; RP/ Points at next option
; OPC/ Count reduced if copied
; OPP/ Pointer updated if copied
SIDCPY: ; Copy option
SUB OPC,OPT ; Remaining free send bytes tobe
IDPB OPT,OPP ; Copy length
ILDB OPT,RP ; and rest
SOSLE OPL
JRST .-3
ILDB OPL,OPP ; Both point at start of next
AOS (P) ; Skip MERGED since copied it
RET
; IP and TCP Information Tables
ICPY==CPYOPT ; IP copy-on-fragmentation
TCPY==0 ; TCP doesn't have such a bit
DEFINE INFOW (NAM,INST)<
NAM==.-..X
INST
> ; End of INFOW
DEFINE INFO (W)<
..X=.
INFOW(CPY,<W'CPY>)
INFOW(LOF,<LOAD OPTS,T'W'OPF,(TCB)>)
INFOW(LOR,<LOAD RC,T'W'POR,(TCB)>)
INFOW(LOU,<LOAD OPP,T'W'POU,(TCB)>)
INFOW(MXW,<MAX'W'OW>)
INFOW(OTAB,<MSEC1,,W'OPNU>)
INFOW(POR,<POINT 8,TCB'W'R(TCB),7>)
INFOW(SDO,<STOR OPP,T'W'PDO,(TCB)>)
INFOW(SOF,<STOR OPTS,T'W'OPF,(TCB)>)
INFOW(SOR,<STOR RC,T'W'POR,(TCB)>)
INFOW(SOU,<STOR T3,T'W'POU,(TCB)>)
INFOW(XFOR,<XMOVEI T2,TCB'W'R(TCB)>)
INFOW(XFOU,<XMOVEI T2,TCB'W'U(TCB)>)
INFOW(XTOO,<XMOVEI T3,TCB'W'O(TCB)>)
INFOW(XTOR,<XMOVEI T3,TCB'W'R(TCB)>)
INFOW(XTOU,<XMOVEI T3,TCB'W'U(TCB)>)
PURGE ..X
> ; End of DEFINE INFO
IPINFO: INFO (I) ; IP Info Table
TCPINFO:INFO (T) ; TCP Info Table
; Restore registers and clean up stack
OPRES: MOVEI 11,REGS ; Saved registers
HRLZS 11 ; REGS,,0
BLT 11,11 ; Restore them
; MOVE 11,11+REGS ; and last
JFCL
RESTORE
RET ; To R: then to caller
; SNDSOP Send a Secure Open Option (Internet)
;TCB/ (Extended) Locked connection block
;PKT/ (Extended) Packet
;
; CALL SNDSOP
;Ret+1: always.
REPEAT 0,<
SNDSOP::
TEMP <PTR>
MOVEI T1,SOPLEN ; Length of option
CALL INOPTR ; Get byte pointer to it
JUMPE PTR,SNDSOX ; No room for it
MOVEI T2,SOPOPT ; Option kind
IDPB T2,PTR ; Store in packet
MOVEI T2,SOPLEN ; Length
IDPB T2,PTR
LOAD T2,TSLVN,(TCB) ; Get next security level
ROT T2,-8 ; Do 2 bytes
IDPB T2,PTR ; Store the high byte
ROT T2,8
IDPB T2,PTR ; and the low byte
SNDSOX: RESTORE
RET
> ; End of REPEAT 0
; SNDSCL Send a Secure Close Option (Internet)
;PKT/ (Extended) Packet
;
; CALL SNDSCL
;Ret+1: always
SNDSCL::
REPEAT 0,<
TEMP <PTR>
MOVEI T1,SCLLEN ; Length of option
CALL INOPTR ; Get a pointer to it
JUMPE PTR,SNDSCX ; No space
MOVEI T2,SCLOPT ; Kind
IDPB T2,PTR
MOVEI T2,SCLLEN ; Length
IDPB T2,PTR
SNDSCX: RESTORE
> ; End of REPEAT 0
RET
REPEAT 0,<
; SETLAB Set debugging label (TCP)
;T1/ Number
;PKT/ (Extended) Packet
;TPKT/ (Extended) TCP packet pointer
;
; CALL SETLAB
;Ret+1: always
SETLAB::TEMP <PTR,LBL>
PUSH P,T1 ; Save the number for awhile
MOVEI T1,LBLLEN ; Length of option
CALL TCOPTR ; Get byte pointer to it
POP P,LBL ; Get back the argument
JUMPE PTR,SETLBX ; No space for it
MOVEI T3,LBLOPT
IDPB T3,PTR
MOVEI T3,LBLLEN ; Length
IDPB T3,PTR
ROT LBL,-8 ; Get high byte
IDPB LBL,PTR
ROT LBL,8
IDPB LBL,PTR
SETLBX: RESTORE
RET
; GETLAB Get debugging label from packet (TCP)
;PKT/ (Extended) Packet
;TPKT/ (Extended) TCP packet pointer
;
; CALL GETLAB
;Ret+1: always, T1 having -1 or the label contents
GETLAB::TEMP <VAL,PTR,LB>
MOVEI T1,LBLOPT ; What to look for in packet
MOVEI T2,LBLLEN ; Expected length
CALL FNTCOP ; Find the option
JUMPE T1,GETLBM ; Couldn't find it. Return -1
MOVEM T1,PTR
ILDB VAL,PTR ; Get high byte
LSH VAL,8 ; Position it
ILDB LB,PTR ; Get low byte
TROA VAL,0(LB) ; Merge the two
GETLBM: SETO VAL,
RESTORE
RET
> ; End of REPEAT 0
REPEAT 0,<
; RSVTSO(PKT) Reserver space in packet for later use to hold timestamp
;PKT/ (Extended) Packet
;TPKT/ (Extended) TCP packet pointer
; CALL RSVTSO
;Ret+1: Always. No failure indication.
RSVTSO::TEMP <PTR>
MOVEI T1,LTSLEN ; 6 byte option length
CALL TCOPTR ; Get the space reserved
JUMPE PTR,RSVTSX ; None available.
MOVEI T2,LTSOPT ; Local timestamp option
IDPB T2,PTR ; The length
MOVEI T2,LTSLEN
IDPB T2,PTR ; The kind
RSVTSX: RESTORE
RET
; SETTSO(PKT, WHEN) Set the value of the timestamp option (TCP)
;T1/ When (milliseconds)
;PKT/ (Extended) Packet
;TPKT/ (Extended) TCP packet pointer
; CALL SETTSO
;Ret+1: always.
SETTSO::TEMP <PTR,WHEN>
PUSH P,T1
MOVEI T1,LTSOPT ; Local timestamp option
MOVEI T2,LTSLEN ; Expected length thereof
CALL FNTCOP ; Find that (previously reserved) option
POP P,WHEN
SKIPE PTR ; Must have been no space for it.
CALL SET4 ; Set a 4-byte number into packet
RESTORE
RET
> ; End of REPEAT 0
; GETTSO(PKT) Get the value stored in the timestamp option (TCP)
;PKT/ (Extended) Packet
;TPKT/ (Extended) TCP packet pointer
; CALL GETTSO
;Ret+1: Qlways. T1 .LT. 0 if no timestamp, or has the 32-bit timestamp
GETTSO::REPEAT 0,<
MOVEI T1,LTSOPT ; The option to look for
MOVEI T2,LTSLEN ; The length we expect for it
CALL FNTCOP ; Find the option
SKIPN T1 ; Skip if successful
SOSA T1 ; Else return -1
CALL GET4 > ; End Repeat 0; Read a 4-byte word
RET
REPEAT 0,<
; Receive Buffer Size option (TCP)
;T1/ Our buffer size (lt 2**16)
;PKT/ (Extended) pointer to packet
;TPKT/ (Extended) pointer to TCP portion of packet
;
; CALL SETRBS
;Ret+1: Always.
SETRBS::TEMP <PTR,SIZ>
PUSH P,T1 ; Save the size for awhile
MOVEI T1,RBSLEN ; Length of the option
CALL TCOPTR ; Get the space
POP P,SIZ ; Unsave the arg
JUMPE PTR,SETRBX ; See if we got the space
MOVEI T3,RBSOPT ; The option number
IDPB T3,PTR ; Store in packet
MOVEI T3,RBSLEN ; Option length
IDPB T3,PTR ; Insert in packet
ROT SIZ,-8 ; High byte of arg
IDPB SIZ,PTR ; Insert it
ROT SIZ,8 ; Low byte
IDPB SIZ,PTR ; Store it
SETRBX: RESTORE
RET
;PKT/ (Extended) pointer to packet
;TPKT/ (Extended) pointer to TCP portion of packet
;
; CALL GETRBS
;Ret+1: Always. T1 has the buffer size or -1 if option not present
GETRBS::TEMP <SIZ,PTR,LB>
MOVEI T1,RBSOPT ; What to look for
MOVEI T2,RBSLEN ; How long it should be
CALL FNTCOP ; Look in TCP option list
JUMPE T1,GETRBM ; Jump if not there
MOVEM T1,PTR ; Stash the pointer
ILDB SIZ,PTR ; Get the high byte
LSH SIZ,8 ; To right place
ILDB LB,PTR ; Get the low byte
TROA SIZ,0(LB) ; Combine the two
GETRBM: SETO SIZ, ; Say not present
RESTORE
RET
> ; End of REPEAT 0
REPEAT 0,<
; SET4(PTR, DATA, PKT) Set a 4-byte option into a packet
;T1/ Byte pointer into packet (Indexes by PKT or TPKT)
;T2/ 32-bit right justified number to be entered
;PKT/ (Extended) Packet pointer
;TPKT/ (Extended) TCP packet pointer
;
; CALL SET4
;Ret+1: Always
SET4: TEMP <PTR,DATA,CNT>
LSH DATA,4 ; Left justify in word
MOVEI CNT,4 ; How many bytes
SET41: ROT DATA,8 ; Put next byte in low 8 bits
IDPB DATA,PTR ; Store into packet
SOJG CNT,SET41 ; Loop over all bytes
RESTORE
RET
; GET4(PTR, PKT) Read out a 4-byte option value
;T1/ Byte pointer into packet (Indexes by PKT or TPKT)
;PKT/ (Extended) Packet pointer
;TPKT/ (Extended) TCP packet pointer
;
; CALL GET4
;Ret+1: Always. Number in T1.
GET4: TEMP <VAL,PTR,BYT,CNT>
MOVEI CNT,4 ; How many bytes to do
MOVEI VAL,0
GET41: ILDB BYT,PTR
LSH VAL,8
IOR VAL,BYT
SOJG CNT,GET41 ; Loop over all bytes
RESTORE
RET
;INOPTR Get pointer for adding a Internet option
;T1/ Length of the option
;PKT/ (Extended) pointer to the packet
;TPKT/ (Extended) pointer to the TCP portion of the packet
;
; CALL INOPTR
;Ret+1: Always. T1 has pointer or 0 if no space.
INOPTR: LOAD T2,PIDO,(PKT) ; Get current data offset
ASH T2,2 ; As a number of bytes
CAIG T2,MINIHS ; Any options yet?
JRST INOPT1 ; No.
PUSH P,T1 ; Save the length
MOVEI T2,0 ; Say to look for end of options
EXCH T1,T2 ; Put args in right place
CALL FNINOP ; Find the end in the Internet list
POP P,T3 ; Get back the desired length
SKIPE T1 ; Found the end?
CAMGE T2,T3 ; Yes. Nuff space left?
TCPBUG(CHK,<INOPTR: Insufficient Internet option space>,TCPOP1)
LOAD T2,PIDO,(PKT) ; # words IN hdr and options
SUBI T2,<MINIHS+3>/4 ; Compute number of words of options
ASH T2,2 ; Number of bytes in the options area
LDB T4,[POINT 3,T1,2] ; # empty bytes in last word
SUB T2,T4 ; Current # bytes in options area
ADDI T2,3(T3) ; Include this new option
ASH T2,-2 ; Round up, wordwise
STOR T2,PIDO,(PKT) ; Set as new data offset
EXIT INOPTX
INOPT1: ADDI T1,3 ; Set to round up
ASH T1,-2 ; Convert to words
LOAD T2,PIDO,(PKT) ; Get data offset
ADD T1,T2
STOR T1,PIDO,(PKT) ; Make data offset include this option
HRLI T1,(<POINT 8,.-.(PKT)>) ; Construct pointer
INOPTX: RET
; TCOPTR Get pointer for adding a TCP option
;T1/ Length of the the option
;PKT/ (Extended) pointer to the packet
;TPKT/ (Extended) pointer to the TCP portion of the packet
;
; CALL TCOPTR
;Ret+1: Always. T1 has pointer or 0 if no space.
TCOPTR: LOAD T2,PTDO,(TPKT) ; Get current TCP data offset
ASH T2,2 ; In terms of bytes
CAIG T2,MINTHS ; Any options present?
JRST TCOPT1 ; No.
PUSH P,T1 ; Save the length
MOVEI T2,0 ; Say to look for end of options
EXCH T1,T2 ; Put args in right place
CALL FNTCOP ; Find the end in the TCP list
POP P,T3 ; Get back the desired length
SKIPE T1 ; Found the end?
CAMGE T2,T3 ; Yes. Nuff space available?
TCPBUG(CHK,<TCOPTR: Insufficient TCP option space>,TCPOP2)
LOAD T2,PTDO,(TPKT) ; # words TCP hdr and options
SUBI T2,<MINTHS+3>/4 ; Compute number of words of options
ASH T2,2 ; Number of bytes in the options area
LDB T4,[POINT 3,T1,2] ; # empty bytes in last word
SUB T2,T4 ; Current # bytes in options area
ADDI T2,3(T3) ; Include this new option
ASH T2,-2 ; Round up, wordwise
STOR T2,PTDO,(TPKT) ; Set as new TCP data offset
EXIT TCOPTX
TCOPT1: ADDI T1,3 ; Set to round up
ASH T1,-2 ; Number of words needed
LOAD T2,PTDO,(TPKT) ; Data offset in words
ADD T1,T2 ; Make it include this option
STOR T1,PTDO,(TPKT) ; Set into pkt
HRLI T1,(<POINT 8,.-.(TPKT)>) ; Construct pointer
TCOPTX: RET
; FNINOP Return byte pointer for reading an Internet option
;T1/ Kind to look for
;T2/ Expected length of the option or 0 for don't care
;PKT/ (Extended) Packet
;TPKT/ (Extended) TCP packet pointer
;
; CALL FNINOP
;Ret+1: Always. T1 has pointer to option if present, or 0 if not.
; T2 has option length or space left if looking for end.
FNINOP: MOVE T3,[POINT 8,<<MINIHS+3>/4>-1(PKT),31]; Pointer to options
LOAD T4,PIDO,(PKT) ; Current Internet data offset
ASH T4,2 ; As a byte count
SUBI T4,MINIHS ; Max size of option space
CALLRET SCANOP ; Scan for that option. Ret PTR in T1.
; FNTCOP Return byte pointer for reading an TCP option
;T1/ Kind to look for
;T2/ Expected length of the option or 0 for don't care
;PKT/ (Extended) Packet
;TPKT/ (Extended) TCP packet pointer
;
; CALL FNTCOP
;Ret+1: Always. T1 has pointer to option if present, or 0 if not.
; T2 has option length or space left if looking for end.
FNTCOP: MOVE T3,[POINT 8,<<MINTHS+3>/4>-1(TPKT),31]; Pointer to options
LOAD T4,PTDO,(TPKT) ; Current TCP data offset
ASH T4,2 ; As a byte count
SUBI T4,MINTHS ; Max size of option space
CALLRET SCANOP ; Scan for that option. Ret PTR in T1.
; SCANOP Return byte pointer for reading an option
;T1/ Kind to look for
;T2/ Expected length of the option
;T3/ (Extended) pointer where to start
;T4/ Maximum number of bytes to scan
;PKT/ (Extended) Packet
;TPKT/ (Extended) TCP packet pointer
;
; CALL SCANOP
;Ret+1: Always. T1 has pointer to option data, or 0 if not found.
; T2 has length of option or space left if scanning
; for end option. In this case T1 is set to
; overwrite the end option.
SCANOP: LOCAL <KIND,EXPLEN,OPTLEN>
DMOVEM T1,KIND ; T1 to KIND, T2 to EXPLEN
SCANO1: JUMPLE T4,SCANO6 ; Fail if entire area scanned
MOVE T1,T3 ; T1 has ptr to start of this option
ILDB OPTLEN,T3 ; Get the kind byte
JUMPN OPTLEN,SCANO2 ; Jump if not end mark
JUMPN KIND,SCANO6 ; Fail if not looking for end
MOVE T2,T4 ; Set to return space left in T2
JRST SCANO7 ; T1 has pointer to end option
SCANO2: CAIE OPTLEN,NOPOPT ; NOP option?
JRST SCANO3 ; No.
CAIE KIND,NOPOPT ; Looking for padding?
SOJA T4,SCANO1 ; No. Reduce space left and continue.
JRST SCANO7 ; Return pointer in T1
SCANO3: CAME OPTLEN,KIND ; Found what we are looking for?
JRST SCANO4 ; No. Check next one.
ILDB OPTLEN,T3 ; Get the length for real
JUMPE EXPLEN,SCANO5 ; Don't care what length is?
CAMN OPTLEN,EXPLEN ; Or length matches?
JRST SCANO5 ; Yes. Go check kind.
SCANO4: SUB T4,OPTLEN ; Advance to next option
IFNKA < ADJBP OPTLEN,T1 ; Bump pointer
MOVE T3,OPTLEN ; And put it in standard place
>
IFKA < IBP T1
SOJG OPTLEN,.-1
MOVE T3,T1
>
JRST SCANO1 ; Try next option.
SCANO5: MOVE T1,T3 ; Yes. Get pointer to data part.
SKIPA T2,OPTLEN ; Set to return length.
SCANO6: SETZ T1, ; Failure indication
SCANO7: RESTORE
RET
> ; End of REPEAT 0
TNXEN